/*
 *  Autores: Claudio Djohnnatha, David Guilherme, Jailson Lima e Jordan Lira.
 *
 *  Projeto da disciplina Linguagem de Programação 2.
 *
 *  Arquivo: ManagementProtocol.java
 *
 *  Descrição: Gerencia os ProtocolComunication para cada documento aberto no servidor.
 *
 *  Data: 27/08/2013
 *
 */



import java.util.LinkedList;
import java.io.File;

public class ManagementProtocol
{
   // Lista com os ProtocolComunication dos referente aos documentos que estão atualmente sendo editados.
   private LinkedList< ProtocolComunication > list_protocol;

   // Objeto com a lista de nomes de todos os documentos existentes no banco de dados do servidor.
   private ListDocuments list_documents;

   // Objetos para gravação e leitura no banco de dados.
   private CreateSequentialDocument create_document;
   private ReadSequentialDocument read_document;
   private CreateSequentialList create_list;
   private ReadSequentialList read_list;

   public ManagementProtocol()
   {
      list_protocol = new LinkedList< ProtocolComunication >();

      // Cria objetos para gravação e leitura.
      create_document = new CreateSequentialDocument();
      read_document = new ReadSequentialDocument();
      create_list = new CreateSequentialList();
      read_list = new ReadSequentialList();

      // Inicializa o banco de dados.
      initDataBase();
   }

   public String listDocuments()
   {
      return list_documents.getListNames();
   }

   public ProtocolComunication newDocument( String title )
   {
      ProtocolComunication protocol = new ProtocolComunication( new Document( title, "" ) );
      list_protocol.add( protocol );
      return protocol;
   }

   public ProtocolComunication openDocument( String title ) throws Exception
   {
      if ( !list_documents.exists( title ) )
         throw new Exception();

      // Procura por algum ProtocolComunication que esteja gerenciando a escrita do documento com o título
      // passado como parâmetro.
      for ( int count = 0; count < list_protocol.size(); count++ )
         if ( list_protocol.get( count ).getTitle().equals( title ) )
            return list_protocol.get( count );

      // Se a execução chegou nesse ponto é porque não tem nenhum ProtocolComunication para esse documento, então
      // vamos instânciar um novo ProtocolComunication para gerenciar a escrita desse documento.
      // Carrega o documento do banco de dados.
      read_document.openFile( title );
      Document document = read_document.readRecords();
      read_document.closeFile();

      // Cria o protocolo para o documento.
      ProtocolComunication protocol = new ProtocolComunication( document );
      list_protocol.add( protocol );
      return protocol;
   }

   // IMPORTANTE: LEMBRAR DE ATUALIZAR A LISTA DE DOCUMENTOS PARA TODOS OS CLIENTES DO SERVIDOR NO FINAL DO MÉTODO SAVE!
   public synchronized void saveDocument( Document document )
   {
      // Salva o Document no banco de dados.
      create_document.openFile( document.getTitle() );
      create_document.addRecords( document );
      create_document.closeFile();

      // Verifica se o documento que será salvo já existe na lista do banco de dados.
      if ( list_documents.exists( document.getTitle() ) )
         return;

      // Atualiza a lista de nomes de documentos no servidor.
      list_documents.add( document.getTitle() );

      // Salva o ListDocuments no banco de dados.
      create_list.openFile();
      create_list.addRecords( list_documents );
      create_list.closeFile();
   }

   public synchronized void renameDocument( ProtocolComunication protocol, String new_title )
   {
      // Verifica se o documento que será renomeado já existe na lista do banco de dados.
      if ( list_documents.exists( protocol.getTitle() ) )
      {
         Document document = protocol.getDocument();
         document.setTitle( new_title );

         // Deleta o arquivo com o nome antigo.
         String path = "DataBase\\" + protocol.getTitle() + ".ser";
         File file = new File( path );
         file.delete();

         // Salva o Document no banco de dados.
         create_document.openFile( new_title );
         create_document.addRecords( document );
         create_document.closeFile();

         list_documents.remove( protocol.getTitle() );
         list_documents.add( new_title );

         // Salva o ListDocuments no banco de dados.
         create_list.openFile();
         create_list.addRecords( list_documents );
         create_list.closeFile();
      }

      protocol.renameTitle( new_title );

      /* Quando algum documento é renomeado uma mensagem de atualização é distribuída para
       * todos os ClientApplication no servidor, exceto para os que estiverem sem documento aberto, pois
       * como não estão atualmente vinculados a um ProtocolComunication eles não receberão essa atualização.
       * Caso esses clientes tentem abrir um documento que não existe mais no servidor, por conta de uma
       * renomeação ou exclusão eles receberão um mensagem do servidor indicando que o arquivo não existe
       * mais e receberão automáticamente uma atualização da lista de documentos atual do servidor.
       */

      String message_update = listDocuments() + " LIST_DOC";
      updateServer( message_update );
   }

   // Retorna 0 se o documento foi deletado do servidor, e 1 em caso contrário.
   public synchronized void deleteDocument( ProtocolComunication protocol ) throws Exception
   {
      if ( protocol.sizeListProtocolServer() == 1 )
      {
         String path = "DataBase\\" + protocol.getTitle() + ".ser";
         File file = new File( path );
         if ( file.exists() )
         {
            file.delete();

            list_documents.remove( protocol.getTitle() );

            // Salva o ListDocuments no banco de dados.
            create_list.openFile();
            create_list.addRecords( list_documents );
            create_list.closeFile();
         }

         list_protocol.remove( protocol );

      }
      else
         throw new Exception(); // Não foi possível deletar pois exitem outros clientes no servidor editando o documento.

   }

   // Atualização enviada do servidor se algum documento for renomeado ou excluído.
   public synchronized void updateServer( String message_update )
   {
      for ( int count = 0; count < list_protocol.size(); count++ )
         list_protocol.get( count ).updateServer( message_update );
   }

   // Inicializa o banco de dados do servidor.
   public void initDataBase()
   {
      File pasta = new File( "DataBase\\List" );
      if ( !pasta.exists() ) // A pasta não existe.
      {
         pasta.mkdirs(); // Cria a pasta.
      }

      // Faz a primeira gravação se no banco de dados não existir o arquivo "DataBase\\List\\list_documents.ser".
      File file = new File( "DataBase\\List\\list_documents.ser" );
      if ( !file.exists() ) // Não há banco de dados salvo.
      {
         create_list.openFile();
         create_list.addRecords( new ListDocuments() );
         create_list.closeFile();
      }

      // Faz a primeira leitura no banco de dados.
      read_list.openFile();
      list_documents = read_list.readRecords();
      read_list.closeFile();
   }

}